using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace App16._2
{
    /// <summary>
    /// Interaction logic for SearchControl.xaml
    /// </summary>

    public partial class SearchControl : System.Windows.Controls.UserControl
    {
        public SearchControl()
        {
            InitializeComponent();

            HistoryList forwardStack = new HistoryList();
            SetValue(ForwardStackPropertyKey, forwardStack);
            HistoryList backStack = new HistoryList();
            SetValue(BackStackPropertyKey, backStack);

            ForwardStack.IsEmptyChanged += OnIsForwardStackEmptyChanged;
            BackStack.IsEmptyChanged += OnIsBackStackEmptyChanged;

            Binding forwardBinding = new Binding("CanGoForward");
            forwardBinding.ElementName = "searchControl";
            forwardButton.SetBinding(Button.IsEnabledProperty, forwardBinding);
            Binding backBinding = new Binding("CanGoBack");
            backBinding.ElementName = "searchControl";
            backButton.SetBinding(Button.IsEnabledProperty, backBinding);

            BindingExpression forwardExpression =
                BindingOperations.GetBindingExpression(forwardButton,
                Button.IsEnabledProperty);
            forwardExpression.UpdateTarget();
            BindingExpression backExpression =
                BindingOperations.GetBindingExpression(backButton,
                Button.IsEnabledProperty);
            backExpression.UpdateTarget();
        }

        internal static readonly DependencyPropertyKey CanGoForwardPropertyKey =
            DependencyProperty.RegisterReadOnly("CanGoForward", typeof(bool),
            typeof(SearchControl), new PropertyMetadata(false));
        internal static readonly DependencyPropertyKey CanGoBackPropertyKey =
            DependencyProperty.RegisterReadOnly("CanGoBack", typeof(bool),
            typeof(SearchControl), new PropertyMetadata(false));
        internal static readonly DependencyPropertyKey ForwardStackPropertyKey =
            DependencyProperty.RegisterReadOnly("ForwardStack", typeof(HistoryList),
            typeof(SearchControl), new PropertyMetadata());
        internal static readonly DependencyPropertyKey BackStackPropertyKey =
            DependencyProperty.RegisterReadOnly("BackStack", typeof(HistoryList),
            typeof(SearchControl), new PropertyMetadata());

        private static readonly DependencyProperty CanGoForwardProperty =
            CanGoForwardPropertyKey.DependencyProperty;
        private static readonly DependencyProperty CanGoBackProperty =
            CanGoBackPropertyKey.DependencyProperty;
        private static readonly DependencyProperty ForwardStackProperty =
            ForwardStackPropertyKey.DependencyProperty;
        private static readonly DependencyProperty BackStackProperty =
            BackStackPropertyKey.DependencyProperty;

        public bool CanGoForward
        {
            get { return (bool)GetValue(CanGoForwardProperty); }
        }

        public bool CanGoBack
        {
            get { return (bool)GetValue(CanGoBackProperty); }
        }

        private HistoryList ForwardStack
        {
            get { return (HistoryList)GetValue(ForwardStackProperty); }
        }

        private HistoryList BackStack
        {
            get { return (HistoryList)GetValue(BackStackProperty); }
        }

        public void OnIsForwardStackEmptyChanged(object sender, EventArgs args)
        {
            SetValue(CanGoForwardPropertyKey, ForwardStack.Count != 0);
        }

        public void OnIsBackStackEmptyChanged(object sender, EventArgs args)
        {
            SetValue(CanGoBackPropertyKey, BackStack.Count != 0);
        }

        public void GoForward()
        {
            if (CanGoForward)
            {
                contentEdit.Text = ForwardStack[ForwardStack.Count - 1];
                ForwardStack.Pop();
                Search(contentEdit.Text);
            }
        }

        public void GoBack()
        {
            if (CanGoBack)
            {
                contentEdit.Text = BackStack[BackStack.Count - 1];
                BackStack.Pop();
                Search(contentEdit.Text);
            }
        }

        public void OnSearchClicked(object sender, RoutedEventArgs args)
        {
            while (ForwardStack.Count != 0)
                ForwardStack.Pop();
            BackStack.Push(contentEdit.Text);

            Search(contentEdit.Text);
        }

        public void OnForwardClicked(object sender, RoutedEventArgs args)
        {
            GoForward();
        }

        public void OnBackClicked(object sender, RoutedEventArgs args)
        {
            GoBack();
        }

        public void OnEditKeyDown(object sender, KeyEventArgs args)
        {
            if (args.Key == Key.Enter)
            {
                while (ForwardStack.Count != 0)
                    ForwardStack.Pop();
                BackStack.Push(contentEdit.Text);

                Search(contentEdit.Text);
            }
        }

        public void Search(string content)
        {
            //There defines the search functionality...
        }

        private class HistoryList : List<string>
        {
            public HistoryList()
                : base()
            { }

            public event System.ComponentModel.PropertyChangedEventHandler IsEmptyChanged;

            public void Push(string item)
            {
                base.Add(item);
                if (Count == 1)
                    IsEmptyChanged(this,
                    new System.ComponentModel.PropertyChangedEventArgs("History"));
            }

            public void Pop()
            {
                base.RemoveAt(Count - 1);
                if (Count == 0)
                    IsEmptyChanged(this,
                    new System.ComponentModel.PropertyChangedEventArgs("IsEmpty"));
            }
        }
    }
}